﻿// Copyright (c) 2012 Francis Xavier Joseph Pulikotil
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

using System;
using System.IO;

namespace Daabli
{
    public static class ArrayExtensions
    {
        public static bool Contains<T>(this T[] array, T element)
        {
            foreach (T item in array)
                if (item.Equals(element))
                    return true;

            return false;
        }
    }

    public static class ReaderExtensions
    {
        public static bool FromStream(this Reader r, Stream stream)
        {
            if (stream == null)
            {
                r.Log.Write(MessageType.InvalidArgument, "cannot read from null stream");
                return false;
            }

            var data = string.Empty;
            try
            {
                using (var streamReader = new StreamReader(stream))
                    data = streamReader.ReadToEnd();
            }
            catch (Exception)
            {
                r.Log.Write(MessageType.Error, "failed to read data from stream");
                return false;
            }

            return r.FromData(data);
        }

        public static bool RegisterTypeName<T>(this Reader r) where T : new()
        {
            Type type = typeof(T);
            return r.RegisterTypeName(type.Name, type);
        }
        public static bool UnregisterTypeName<T>(this Reader r) where T : new()
        {
            Type type = typeof(T);
            return r.UnregisterTypeName(type.Name);
        }

        public static bool RegisterDefaultObjectReaders(this Reader r)
        {
            return
                // basic readers
                r.RegisterObjectReader(new BoolReader()) &&
                r.RegisterObjectReader(new ValueReader<byte>(byte.TryParse)) &&
                r.RegisterObjectReader(new ValueReader<sbyte>(sbyte.TryParse)) &&
                r.RegisterObjectReader(new CharReader()) &&
                r.RegisterObjectReader(new ValueReader<decimal>(decimal.TryParse)) &&
                r.RegisterObjectReader(new ValueReader<double>(double.TryParse)) &&
                r.RegisterObjectReader(new ValueReader<float>(float.TryParse)) &&
                r.RegisterObjectReader(new ValueReader<int>(int.TryParse)) &&
                r.RegisterObjectReader(new ValueReader<uint>(uint.TryParse)) &&
                r.RegisterObjectReader(new ValueReader<long>(long.TryParse)) &&
                r.RegisterObjectReader(new ValueReader<ulong>(ulong.TryParse)) &&
                r.RegisterObjectReader(new ValueReader<short>(short.TryParse)) &&
                r.RegisterObjectReader(new ValueReader<ushort>(ushort.TryParse)) &&
                r.RegisterObjectReader(new StringReader()) &&

                // container readers
                r.RegisterObjectReader(new ListReader()) &&
                r.RegisterObjectReader(new DictionaryReader()) &&
                r.RegisterObjectReader(new QueueReader()) &&
                r.RegisterObjectReader(new StackReader()) &&
                r.RegisterObjectReader(new LinkedListReader()) &&

                // Insert additional registrations above this line
                true;
        }
        public static bool RegisterDefaultTypeNames(this Reader r)
        {
            return
                // basic types
                r.RegisterTypeName<bool>() &&
                r.RegisterTypeName<byte>() &&
                r.RegisterTypeName<sbyte>() &&
                r.RegisterTypeName<char>() &&
                r.RegisterTypeName<decimal>() &&
                r.RegisterTypeName<double>() &&
                r.RegisterTypeName<float>() &&
                r.RegisterTypeName<int>() &&
                r.RegisterTypeName<uint>() &&
                r.RegisterTypeName<long>() &&
                r.RegisterTypeName<ulong>() &&
                r.RegisterTypeName<short>() &&
                r.RegisterTypeName<ushort>() &&
                r.RegisterTypeName("string", typeof(string)) &&

                // Insert additional registrations above this line
                true;
        }
    }
}
